//
// Created by denglibin on 19-4-9.
//
/**
 * 函数定义：ssize_t write (int fd, const void * buf, size_t count);

函数说明：write()会把参数buf所指的内存写入count个字节到参数放到所指的文件内。并且移动文件读写位置。

返回值：如果顺利write()会返回实际写入的字节数。当有错误发生时则返回-1，错误代码存入errno中

 write()函数返回值一般无0，只有当如下情况发生时才会返回0：write(fp, p1+len, (strlen(p1)-len)中第三参数为0，此时write()什么也不做，只返回0

 write()函数从buf写数据到fd中时，若buf中数据无法一次性读完，那么第二次读buf中数据时，其读位置指针（也就是第二个参数buf）不会自动移动，需要程序员编程控制，
而不是简单的将buf首地址填入第二参数即可。如可按如下格式实现读位置移动：write(fp, p1+len, (strlen(p1)-len)。 这样write第二次循环时变会从p1+len处写数据到fp, 之后的也
由此类推，直至(strlen(p1)-len变为0。

 3）在write一次可以写的最大数据范围内（貌似是BUFSIZ ,8192），第三参数count大小最好为buf中数据的大小，以免出现错误。(经过笔者再次试验，write一次能够写入的并不只有8192这么多，
 笔者尝试一次写入81920000，结果也是可以，看来其一次最大写入数据并不是8192，但内核中确实有BUFSIZ这个参数，具体指什么还有待研究)
 */
#include <unistd.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>

static int main_(){

    char * path = "/home/denglibin/open.txt";
    int fd = open(path, O_WRONLY | O_CREAT | O_APPEND | O_NONBLOCK, 0644);
    if(fd == -1){
        perror("open");
        return -1;
    }
    int writeLen;
    char * str = "\n中华人民共和国！";
    int strLen = strlen(str);

    while (writeLen = write(fd, str, strLen) < strLen){
        if(writeLen == -1){
            if(errno == EINTR){ //调用返回-1并且errno被设置成EINTR。表示在读入之前收到了一个信号，可以重新进行调用
                continue;
            }
            if(errno = EAGAIN){ //非阻塞模式,写操作正常阻塞时返回-1并且errno被设置成EAGAIN。请求应该在稍后重新发起。通常处理普通文件不会出现这种情况
                perror("write");
                break;
            }
        }
        str += writeLen;//移动指针
        strLen -= writeLen; //下次要读的字节数量
    }
   // fsync(fd);//同步io 调用fsync(fd); 可以保证fd对应的文件的脏数据回写到磁盘上。fd必须是以写的方式打开
    fdatasync(fd); //和sync 一样 该调用不保证元数据同步到磁盘上，故此可能会快一些
    //sync();//可以用来对磁盘上的所有缓冲区进行同步，尽管其效率不高，但仍然被广泛使用，
    //它总是返回成功，并确保所有的缓冲区包括数据和元数据都能被写入磁盘

    close(fd);
    return 0;

}